//package com.cebbank.sz.cebtemplate.config;
//
//
//import com.cebbank.sz.cebtemplate.annotation.CacheExpire;
//import org.springframework.beans.BeansException;
//import org.springframework.beans.factory.InitializingBean;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.cache.Cache;
//import org.springframework.cache.annotation.CacheConfig;
//import org.springframework.cache.annotation.Cacheable;
//import org.springframework.cache.annotation.Caching;
//import org.springframework.context.ApplicationContext;
//import org.springframework.context.ApplicationContextAware;
//import org.springframework.core.annotation.AnnotationUtils;
//import org.springframework.data.redis.cache.RedisCache;
//import org.springframework.data.redis.cache.RedisCacheConfiguration;
//import org.springframework.data.redis.cache.RedisCacheManager;
//import org.springframework.data.redis.cache.RedisCacheWriter;
//import org.springframework.data.redis.core.RedisTemplate;
//import org.springframework.data.redis.serializer.RedisSerializationContext;
//import org.springframework.util.ReflectionUtils;
//
//import java.time.Duration;
//import java.util.*;
//import java.util.concurrent.Callable;
///**
// * @author daigl
// * @create 2019/12/4
// **/
//public class ExtendExpireCacheManager extends RedisCacheManager implements ApplicationContextAware, InitializingBean {
//
//    @Autowired
//    private RedisTemplate redisTemplate;
//    /**
//     * spring应用程序上下文
//     */
//    private ApplicationContext applicationContext;
//    /**
//     * Cache配置链表
//     */
//    private Map<String, RedisCacheConfiguration> initialCacheConfiguration = new LinkedHashMap<>();
//
//    @Override
//    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//        this.applicationContext = applicationContext;
//    }
//
//    public ExtendExpireCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
//        super(cacheWriter, defaultCacheConfiguration);
//    }
//
//    @Override
//    public Cache getCache(String name) {
//        Cache cache = super.getCache(name);
//        return new RedisCacheWrapper(cache);
//    }
//
//    @Override
//    public void afterPropertiesSet() {
//        String[] beanNames = applicationContext.getBeanNamesForType(Object.class);
//        for (String beanName : beanNames) {
//            final Class clazz = applicationContext.getType(beanName);
//            add(clazz);
//        }
//        super.afterPropertiesSet();
//    }
//
//    @Override
//    protected Collection<RedisCache> loadCaches() {
//        List<RedisCache> caches = new LinkedList<>();
//        for (Map.Entry<String, RedisCacheConfiguration> entry : initialCacheConfiguration.entrySet()) {
//            caches.add(super.createRedisCache(entry.getKey(), entry.getValue()));
//        }
//        return caches;
//    }
//
//    private void add(final Class clazz) {
//        ReflectionUtils.doWithMethods(clazz, method -> {
//            ReflectionUtils.makeAccessible(method);
//            CacheExpire cacheExpire = AnnotationUtils.findAnnotation(method, CacheExpire.class);
//            if (cacheExpire == null) {
//                return;
//            }
//            Cacheable cacheable = AnnotationUtils.findAnnotation(method, Cacheable.class);
//            if (cacheable != null) {
//                add(cacheable.cacheNames(), cacheExpire);
//                return;
//            }
//            Caching caching = AnnotationUtils.findAnnotation(method, Caching.class);
//            if (caching != null) {
//                Cacheable[] cs = caching.cacheable();
//                if (cs.length > 0) {
//                    for (Cacheable c : cs) {
//                        if (cacheExpire != null && c != null) {
//                            add(c.cacheNames(), cacheExpire);
//                        }
//                    }
//                }
//            } else {
//                CacheConfig cacheConfig = AnnotationUtils.findAnnotation(clazz, CacheConfig.class);
//                if (cacheConfig != null) {
//                    add(cacheConfig.cacheNames(), cacheExpire);
//                }
//            }
//        }, method -> null != AnnotationUtils.findAnnotation(method, CacheExpire.class));
//    }
//
//    private void add(String[] cacheNames, CacheExpire cacheExpire) {
//        for (String cacheName : cacheNames) {
//            if (cacheName == null || "".equals(cacheName.trim())) {
//                continue;
//            }
//            long expire = cacheExpire.expire();
//            if (expire >= 0) {
//                // 缓存配置
//                RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
//                        .entryTtl(Duration.ofSeconds(expire))
//                        .disableCachingNullValues()
//                        // .prefixKeysWith(cacheName)
//                        .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getStringSerializer()))
//                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));
//                initialCacheConfiguration.put(cacheName, config);
//            }
//        }
//    }
//
//    protected static class RedisCacheWrapper implements Cache {
//
//        private final Cache cache;
//
//        RedisCacheWrapper(Cache cache) {
//            this.cache = cache;
//        }
//
//        @Override
//        public String getName() {
//            try {
//                return cache.getName();
//            } catch (Exception e) {
//                return null;
//            }
//        }
//
//        @Override
//        public Object getNativeCache() {
//            try {
//                return cache.getNativeCache();
//            } catch (Exception e) {
//                return null;
//            }
//        }
//
//        @Override
//        public ValueWrapper get(Object o) {
//            try {
//                return cache.get(o);
//            } catch (Exception e) {
//                return null;
//            }
//        }
//
//        @Override
//        public <T> T get(Object o, Class<T> aClass) {
//            try {
//                return cache.get(o, aClass);
//            } catch (Exception e) {
//                return null;
//            }
//        }
//
//        @Override
//        public <T> T get(Object o, Callable<T> callable) {
//            try {
//                return cache.get(o, callable);
//            } catch (Exception e) {
//                return null;
//            }
//        }
//
//        @Override
//        public void put(Object o, Object o1) {
//            try {
//                cache.put(o, o1);
//            } catch (Exception e) {
//            }
//        }
//
//        @Override
//        public void evict(Object o) {
//            try {
//                cache.evict(o);
//            } catch (Exception e) {
//            }
//        }
//
//        @Override
//        public void clear() {
//            try {
//                cache.clear();
//            } catch (Exception e) {
//            }
//        }
//
//        @Override
//        public ValueWrapper putIfAbsent(Object o, Object o1) {
//            try {
//                return cache.putIfAbsent(o, o1);
//            } catch (Exception e) {
//                return null;
//            }
//        }
//    }
//}
